#pragma once
#include <iostream>
#include <vector>
#include <assert.h>

namespace mylog{
    #define BUFFER_DEFAULT_SIZE (1*1024*1024)
    #define BUFFER_INCREMENT_SIZE (1*1024*1024)
    #define BUFFER_THRESHOLD_SIZE (10*1024*1024)

    class Buffer{
    protected:
        size_t _read_idx = 0;
        size_t _write_idx = 0;
        std::vector<char> _arry;
    protected:
        void EnableWriteSize(size_t len){
            if(len > WriteAbleSize()){
                if(_arry.size() < BUFFER_THRESHOLD_SIZE){
                    _arry.resize(_arry.size() * 2 + len);
                }else{
                    _arry.resize(_arry.size() + len + BUFFER_INCREMENT_SIZE);
                }
            }
            return;
        }
    public:
        Buffer():_arry(BUFFER_DEFAULT_SIZE){}
        void Push(const char* data, size_t len){
            EnableWriteSize(len);
            assert(len < WriteAbleSize());
            std::copy(data, data + len, &_arry[_write_idx]);
            _write_idx += len;
        }
        void Pop(size_t len){
            _read_idx += len;
            assert(_read_idx <= _write_idx);
        }
        void Swap(Buffer& buf){
            _arry.swap(buf._arry);
            std::swap(_read_idx, buf._read_idx);
            std::swap(_write_idx, buf._write_idx);
        }
        size_t ReadAbleSize(){
            return _write_idx - _read_idx;
        }
        size_t WriteAbleSize(){
            return _arry.size() - _write_idx;
        }
        void ReSet(){
            _read_idx = 0;
            _write_idx = 0;
        }
        bool Empty(){
            return _read_idx == _write_idx;
        }
        const char *Begin(){
            return &_arry[_read_idx];
        }
    };
}